//
//  ViewController.m
//  ClassProperties
//
//  Created by 张亮亮 on 2018/4/2.
//  Copyright © 2018年 张亮亮. All rights reserved.
//

#import "ViewController.h"
#import <objc/runtime.h>
#import "ViewController+ClassProperties.h"
@interface ViewController ()

@end

@implementation ViewController

static NSString *_someString = nil;
static NSString *_deferString = nil;

- (void)viewDidLoad {
    [super viewDidLoad];
    ViewController.deferString = @"123";
    NSLog(@"%@", ViewController.deferString);
    // Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - -----
#pragma mark - 自己添加setter与getter方法
//不自动合成setter与getter方法，需要自己实现
+(NSString *)someString {
    return _someString;
}
+ (void)setSomeString:(NSString *)someString {
    _someString = someString;
}

#pragma mark - -----
#pragma mark - 动态添加方法
@dynamic (class) deferString;
NSString *deferString(id self, SEL _cmd) {
    return _deferString;
}
void setDeferString(id self, SEL _cmd, NSString *string) {
    _deferString  = string;
}
+ (BOOL)resolveClassMethod:(SEL)sel {
   
    if (sel == @selector(deferString)) {
#pragma Mark-添加类方法 所以class_addMethod传入的是metaClass，
        Method b = class_getClassMethod([self class], @selector(someString));
        printf("getTypes:%s ", method_getTypeEncoding(b));
        //TYpes ：格式依次是 返回值、参数1、参数2、参数3……
        //每个方法默认传两个参数（self，_cmd），并且永远在1、2位置
    Class metaClass = objc_getMetaClass(class_getName([self class]));
        class_addMethod(metaClass, sel ,(IMP)deferString,"@@:");
        return YES;
    }
    
    if (sel == @selector(setDeferString:)) {
        Method b = class_getClassMethod([self class], @selector(setSomeString:));
        printf("setTypes:%s ", method_getTypeEncoding(b));
        Class metaClass = objc_getMetaClass(class_getName([self class]));
        class_addMethod(metaClass, sel ,(IMP)setDeferString,"v@:@");
        return YES;
    }
    return [super resolveClassMethod:sel];
}

/* https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
Table 6-1  Objective-C type encodings
Code
Meaning
c
A char
i
An int
s
A short
l
A long
l is treated as a 32-bit quantity on 64-bit programs.
q
A long long
C
An unsigned char
I
An unsigned int
S
An unsigned short
L
An unsigned long
Q
An unsigned long long
f
A float
d
A double
B
A C++ bool or a C99 _Bool
v
A void
*
A character string (char *)
@
An object (whether statically typed or typed id)
#
A class object (Class)
:
A method selector (SEL)
[array type]
An array
{name=type...}
A structure
(name=type...)
A union
bnum
A bit field of num bits
^type
A pointer to type
?
An unknown type (among other things, this code is used for function pointers)
*/

@end
